{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. ResNet残差网络"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "非常深的神经网络是很难训练的，因为存在梯度消失和梯度爆炸问题\n",
    "\n",
    "可以利用跳跃连接构建能够训练深度网络的ResNets\n",
    "\n",
    "和利用dropout 正则化防止过拟合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From <ipython-input-1-3c98a8d00530>:7: read_data_sets (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:260: maybe_download (from tensorflow.contrib.learn.python.learn.datasets.base) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please write your own downloading logic.\n",
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:262: extract_images (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting ../data/train-images-idx3-ubyte.gz\n",
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:267: extract_labels (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.data to implement this functionality.\n",
      "Extracting ../data/train-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:110: dense_to_one_hot (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use tf.one_hot on tensors.\n",
      "Extracting ../data/t10k-images-idx3-ubyte.gz\n",
      "Extracting ../data/t10k-labels-idx1-ubyte.gz\n",
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\contrib\\learn\\python\\learn\\datasets\\mnist.py:290: DataSet.__init__ (from tensorflow.contrib.learn.python.learn.datasets.mnist) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Please use alternatives such as official/mnist/dataset.py from tensorflow/models.\n",
      "训练集数量： 55000\n",
      "验证集数量： 5000\n",
      "测试集数量： 10000\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# 载入数据集\n",
    "mnist = input_data.read_data_sets(\"../data/\", one_hot=True)\n",
    "\n",
    "# 显示数据集数量\n",
    "print(\"训练集数量：\", mnist.train.num_examples)\n",
    "print(\"验证集数量：\", mnist.validation.num_examples)\n",
    "print(\"测试集数量：\", mnist.test.num_examples)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. 数据读取"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "利用网上的 MNIST 数据集(http://yann.lecun.com/exdb/mnist/)获取数据集压缩文件（切勿解压）：\n",
    "\n",
    "train-images-idx3-ubyte.gz --- 6万张28x28大小的训练数字图像\n",
    "\n",
    "train-labels-idx1-ubyte.gz --- 6万张训练图像的数字标记\n",
    "\n",
    "t10k-images-idx3-ubyte.gz  --- 1万张28x28大小的测试数字图像\n",
    "\n",
    "t10k-labels-idx1-ubyte.gz  --- 1万张测试图像的数字标记"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "训练图像大小： (55000, 784)\n",
      "训练标签大小： (55000, 10)\n"
     ]
    }
   ],
   "source": [
    "# 显示数据集大小\n",
    "print(\"训练图像大小：\", mnist.train.images.shape)\n",
    "print(\"训练标签大小：\", mnist.train.labels.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]\n"
     ]
    }
   ],
   "source": [
    "# 可视化图像\n",
    "def plot_image(image):\n",
    "    plt.imshow(image.reshape(28, 28), cmap='binary')\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "# 可视化第二张训练图像\n",
    "plot_image(mnist.train.images[2])\n",
    "\n",
    "# 可视化第二张图像的标签\n",
    "print(mnist.train.labels[2])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. 构建模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From c:\\users\\dell\\appdata\\local\\programs\\python\\python37\\lib\\site-packages\\tensorflow\\python\\framework\\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n"
     ]
    }
   ],
   "source": [
    "# 定义训练数据的占位符， x是784个像素点的特征值， y是10分类的标签值\n",
    "x = tf.placeholder(tf.float32, [None, 784], name=\"X\")\n",
    "y = tf.placeholder(tf.float32, [None, 10], name=\"Y\")\n",
    "\n",
    "# 为了使用卷积层，需把x变成一个4d向量，其第2、第3维对应图片的宽、高，最后一维代表图片的颜色通道数\n",
    "x_image = tf.reshape(x, [-1, 28, 28, 1])\n",
    "\n",
    "\n",
    "# 权重W 初始化 从标准差0.1的截断正态分布中输出随机值\n",
    "def weight_variable(shape):\n",
    "    initial = tf.truncated_normal(shape, stddev=0.1)\n",
    "    return tf.Variable(initial)\n",
    "\n",
    "\n",
    "# 权重b 初始化 0.1\n",
    "def bias_variable(shape):\n",
    "    initial = tf.constant(0.1, shape=shape)\n",
    "    return tf.Variable(initial)\n",
    "\n",
    "\n",
    "# 定义1步长的 same卷积\n",
    "def conv2d(x, W):\n",
    "    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')\n",
    "\n",
    "\n",
    "# 定义步长为2 大小2x2的 max pooling\n",
    "def max_pool_2x2(x):\n",
    "    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')\n",
    "\n",
    "\n",
    "def res_block(x, kernal_size_x, kernal_size_y, channel_in, channel_out):\n",
    "    X_shortcut = x\n",
    "    channel_out_half = int(channel_out / 2)\n",
    "    # 第一卷积层\n",
    "    with tf.variable_scope(\"res_conv1\"):\n",
    "        res_w_conv1 = weight_variable([kernal_size_x, kernal_size_y, channel_in, channel_out_half])\n",
    "        res_b_conv1 = bias_variable([channel_out_half])\n",
    "        res_h_conv1 = tf.nn.relu(conv2d(x, res_w_conv1) + res_b_conv1)\n",
    "    # 第二卷积层\n",
    "    with tf.variable_scope(\"res_conv2\"):\n",
    "        res_w_conv2 = weight_variable([kernal_size_x, kernal_size_y, channel_out_half, channel_out])\n",
    "        res_b_conv2 = bias_variable([channel_out])\n",
    "        res_h_conv2 = tf.nn.relu(conv2d(res_h_conv1, res_w_conv2) + res_b_conv2)\n",
    "    # 残差块\n",
    "    with tf.variable_scope(\"shortcut\"):\n",
    "        # 输入层在线性激活之后，维持通道数与第二卷积层相同\n",
    "        res_w_shortcut = weight_variable([1, 1, channel_in, channel_out])\n",
    "        res_b_shortcut = bias_variable([channel_out])\n",
    "        X_shortcut = conv2d(X_shortcut, res_w_shortcut) + res_b_shortcut\n",
    "        # 在ReLU激活之前，与第二卷积层相加，产生了一个残差块\n",
    "        res_add = tf.add(res_h_conv2, X_shortcut)\n",
    "        res_b_shortcut = bias_variable([channel_out])\n",
    "        res_add_result = tf.nn.relu(res_add + res_b_shortcut)\n",
    "\n",
    "    return res_add_result\n",
    "\n",
    "\n",
    "# 第一个残差块\n",
    "h_res1 = res_block(x_image, 3, 3, 1, 32)\n",
    "# 第一层池化\n",
    "h_pool1 = max_pool_2x2(h_res1)\n",
    "# 进行局部响应归一化操作\n",
    "h1 = tf.nn.lrn(h_pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)\n",
    "\n",
    "# 第二个残差块\n",
    "h_res2 = res_block(h1, 5, 5, 32, 64)\n",
    "# 第二层池化\n",
    "h_pool2 = max_pool_2x2(h_res2)\n",
    "# 进行局部响应归一化操作\n",
    "h2 = tf.nn.lrn(h_pool2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)\n",
    "h2_flat = tf.reshape(h2, shape=[-1, 7 * 7 * 64])  # 重新展开\n",
    "\n",
    "# 第三阶段全连接层1\n",
    "W_fc1 = weight_variable([7 * 7 * 64, 1024])\n",
    "b_fc1 = bias_variable([1024])\n",
    "h_fc1 = tf.nn.relu(tf.matmul(h2_flat, W_fc1) + b_fc1)\n",
    "\n",
    "# 第四阶段dropout层\n",
    "dropout_rate = tf.placeholder(\"float\")\n",
    "h_fc1_drop = tf.nn.dropout(h_fc1, rate=dropout_rate)\n",
    "\n",
    "# 第五阶段全连接层2\n",
    "W_fc2 = weight_variable([1024, 10])\n",
    "b_fc2 = bias_variable([10])\n",
    "forward = tf.matmul(h_fc1_drop, W_fc2) + b_fc2\n",
    "pred = tf.nn.softmax(forward)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 4. 训练模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Train Epoch 01 Loss= 0.103925243 Accuracy= 0.9712\n",
      "Train Epoch 02 Loss= 0.068904892 Accuracy= 0.9808\n",
      "Train Epoch 03 Loss= 0.052916307 Accuracy= 0.9846\n",
      "Train Epoch 04 Loss= 0.047417201 Accuracy= 0.9878\n",
      "Train Epoch 05 Loss= 0.045173906 Accuracy= 0.9876\n",
      "Train Epoch 06 Loss= 0.041291334 Accuracy= 0.9880\n",
      "Train Epoch 07 Loss= 0.040540095 Accuracy= 0.9882\n",
      "Train Epoch 08 Loss= 0.044096928 Accuracy= 0.9872\n",
      "Train Epoch 09 Loss= 0.044790849 Accuracy= 0.9892\n",
      "Train Epoch 10 Loss= 0.036397565 Accuracy= 0.9898\n",
      "Train Epoch 11 Loss= 0.043122139 Accuracy= 0.9884\n",
      "Train Epoch 12 Loss= 0.037767597 Accuracy= 0.9896\n",
      "Train Epoch 13 Loss= 0.035879690 Accuracy= 0.9890\n",
      "Train Epoch 14 Loss= 0.028891217 Accuracy= 0.9916\n",
      "Train Epoch 15 Loss= 0.041857451 Accuracy= 0.9914\n",
      "Train Epoch 16 Loss= 0.036687627 Accuracy= 0.9908\n",
      "Train Epoch 17 Loss= 0.031272657 Accuracy= 0.9926\n",
      "Train Epoch 18 Loss= 0.041658025 Accuracy= 0.9912\n",
      "Train Epoch 19 Loss= 0.031089630 Accuracy= 0.9920\n",
      "Train Epoch 20 Loss= 0.033109900 Accuracy= 0.9936\n"
     ]
    }
   ],
   "source": [
    "train_epochs = 20  # 迭代次数\n",
    "learning_rate = 1e-3  # 学习率\n",
    "\n",
    "# 定义损失函数\n",
    "with tf.name_scope(\"LossFunction\"):\n",
    "    loss_function = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=forward, labels=y))\n",
    "    \n",
    "# Adam优化器 设置学习率和优化目标损失最小化\n",
    "optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss_function)\n",
    "\n",
    "# 定义预测类别匹配情况\n",
    "correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))\n",
    "\n",
    "# 定义准确率，将布尔值转化成浮点数，再求平均值\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_prediction, \"float\"))\n",
    "\n",
    "sess = tf.Session()  # 建立会话\n",
    "init = tf.global_variables_initializer()  # 变量初始化\n",
    "sess.run(init)\n",
    "\n",
    "# 每个批次的大小，每次放入的大小，每次放入 100张图片 以矩阵的方式\n",
    "batch_size = 100\n",
    "\n",
    "# 计算一共有多少个批次，数量整除大小训练出有多少批次\n",
    "n_batch = mnist.train.num_examples // batch_size\n",
    "\n",
    "for epoch in range(train_epochs):\n",
    "    for batch in range(n_batch):\n",
    "        xs, ys = mnist.train.next_batch(batch_size)\n",
    "        sess.run(optimizer, feed_dict={x: xs, y: ys, dropout_rate: 0.5})\n",
    "        # 批次训练完成之后，使用验证数据计算误差与准确率\n",
    "    loss, acc = sess.run([loss_function, accuracy],\n",
    "                         feed_dict={x: mnist.validation.images,\n",
    "                                    y: mnist.validation.labels,\n",
    "                                    dropout_rate: 0})\n",
    "    # 显示训练信息\n",
    "    print(\"Train Epoch\", '%02d' % (epoch + 1), \"Loss=\", '{:.9f}'.format(loss),\n",
    "          \"Accuracy=\", \"{:.4f}\".format(acc))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 5. 评估模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test Accuracy =  0.9925\n",
      "Validation Accuracy =  0.9936\n"
     ]
    }
   ],
   "source": [
    "# 测试集上评估模型预测的准确率\n",
    "accu_test = sess.run(accuracy, feed_dict={x: mnist.test.images,\n",
    "                                          y: mnist.test.labels,\n",
    "                                          dropout_rate: 0})\n",
    "print(\"Test Accuracy = \", accu_test)\n",
    "\n",
    "# 验证集上评估模型预测的准确率\n",
    "accu_validation = sess.run(accuracy, feed_dict={x: mnist.validation.images,\n",
    "                                                y: mnist.validation.labels,\n",
    "                                                dropout_rate: 0})\n",
    "print(\"Validation Accuracy = \", accu_validation)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 6. 模型预测"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[3 9 5 2 1 3 1 3 6 5]\n"
     ]
    }
   ],
   "source": [
    "# 转换pred预测结果独热编码格式为数字0-9\n",
    "prediction_result = sess.run(tf.argmax(pred, 1), feed_dict={x: mnist.test.images, dropout_rate: 0})\n",
    "\n",
    "# 查看第500-509张测试图片的预测结果\n",
    "print(prediction_result[500:510])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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5D12iIiIiMh77BARERGR99ghIiIiIu+xQ0RERETeY4eIiIiIvMcOEREREXmPHSIiIiLyHjtERERE5L2EnmVGRESl36hRo5z0li1boh571113mVgkueedKqWilvHQQw+ZuE+fPkmVT5QOHCEiIiIi77FDRERERN7Lqimz5cuXO+mDBw+auEaNGk7e6NGjTbx27Von79lnn41Y/rnnnuukO3ToYOJLLrnEyWvUqFEcNSai4rBgwQITDx061Mm7/fbbTXzqqaeWWJ1KuwcffNDEAwYMcPL2798f9XX2FFeyU2bRygOAfv36mdj+mQ8A//znP1M+H6Xm008/ddKXX365iTdv3lzS1SlWHCEiIiIi77FDRERERN5jh4iIiIi8V+JriN5//30n/cknn5j44YcfdvJ++OEHE7du3drJmzFjRtRzRJvnnj17dtT0oEGDnLwxY8ZEPTel7pdffnHSGzZsMPHw4cOdvFdeecXE69ati1rm7373OxN36dLFybv55ptNXLt2bScvHesiKDWLFi1y0ldccYWJw+sU7FvEe/Xq5eS1bdvWxPbPDwCYO3duXHWxyyjNwj9P7XVDsdYM5efnO+k6deqYONlr5ZtvvjHx+vXrnTy7Lv3793fyGjRoYOKuXbsmdW5KzYsvvuik7evv7bffdvLs67Y04ggREREReY8dIiIiIvJeiUyZvfrqqybu2bOnk/fzzz/HVUZ4iqxChQomDk+/2MO6Z511lom//PJL5zh76Hb79u1OXqdOnUy8Zs0aJy8vLy+uOvsu1rTYv//9bycvPCwbTawh+9WrV5vYvsU4nF6xYoWTV79+fRPbnysqXvY2GxdffLGTF74ebe+9917EGACaNm1q4n379jl54evY1rhxYxMvXbo06nGlSfiWdfvaqVWrlpN3ww03mPiaa65x8ho2bJhyXezvffv27Z28L774wsThqbxHHnnExJwyyw725yjXfhdyhIiIiIi8xw4REREReY8dIiIiIvJeiawhsteSxLtmKOzkk0920vat2Xv37nXy7LVCF110kYm///77mGXaOnbsaOIqVaokVlkC4K7pAdx1GrFUrVrVSZcrV87EPXr0MHF4vcGIESNMHL7lOlY9TjnlFBPff//9Tp79eBdKnb1uqE2bNibetm2bc1yyt3fb63+aNGni5MV6zEClSpWSOl9p0qxZMxNPmjTJ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6f/85z8mfuONN5y8ChUqmLh///5OXs+ePYuhduQzjhARERGR99ghIiIiIu9l9ZSZPd01ZcoUJ69v374m3rRpU1xljBs3LupxeXl5TvrFF180ccuWLZ28SpUqRS2HstOkSZNM3KNHDydv2LBhJr766qtLrE656ssvvzRxeHpk/vz5Jn7vvfdMPGjQIOe4AQMGmDjcXtWrV09LPan47Nixw0nbP69feuklJ2/v3r1xlXnPPfc46bZt25r4N7/5TYI1pHgtWLDASe/evdvEo0ePdvL27dtn4hkzZjh569atM/FJJ53k5K1cuTLVaqYFR4iIiIjIe+wQERERkffYISIiIiLvZfUaou3bt5u4ffv2UY8L3yLfokULE0+YMMHEIuIct3XrVhNv27bNybvssstMfNNNNzl5gwcPNnHlypWj1osyZ+HChU66S5cuJg6vAbPbmlLXoEEDE7dr187Je/vtt038008/RS3jjjvuMPH06dOdPPsW/W7dujl59m3alDlnnnmmk16zZk1cr6tfv76T/uqrr0z8/fffO3nffPONibmGKLI9e/Y46SFDhpj4wIEDTt4HH3xg4vXr15t48+bNznGxrttYqlWrZuK6desmVUZx4wgREREReY8dIiIiIvJeVk+Z2bfehm9979Spk4l///vfO3n16tUz8S233GLi8JSZPdwe67a/Z555xknbQ43hvPA5qOT8+OOPJr744oudPHuY1/5cAUCVKlWKt2IeGz58uJO2p5/t2+m/++4757hffvnFxO+8846TN23aNBOH2/nYY49NvrKUMPsW7KZNm5rYvsU67Le//a2Ttre6+Oc//+nk2dOj4Wlwe2qWIlu6dKmT7tevn4l//vnnpMq0pydbtWrl5JUt+2uXIjydffzxx5s4Pz8/qXMXN44QERERkffYISIiIiLvsUNERERE3svqNUTnnXeeicNPo7fXEMUS66n1y5Yti5rXunVrE8+aNcvJs9dF7Nq1y8kbM2ZMXPWi9LMf4RLeRqFZs2Ym7t69e4nVyXc1atRw0vaan7Vr15q4efPmznH27dZhAwcONDHXDJWs8GOS7O1QYq0bsn+WP/XUU05ekyZNor7u8ccfN3F4LVnt2rVj1pUO3f7gueeeM3HVqlWdPHubm2uuucbE5cqVc46z18mWKVMmLfXMFhwhIiIiIu+xQ0RERETey+ops86d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/OynJO/fv9/JC+9iTNllx44dTnrQoEEm/u1vf+vk2dfc559/buLwVhb2rcMvv/xy3HU5/fTT4z6WIrvsssuctL2cYOLEiU5eeKfwQnY7A8Do0aNNbD/dvijc4qRo4W1hli9fXqzn27hxo4kHDhwY9bgbb7zRSVevXr3Y6pQuHCEiIiIi77FDRERERN5jh4iIiIi8l9VriMaPH2/iWFuCb9u2zUnbT6q357LtJ2gDwHfffWfiH3/80cmzz1e7dm0nb+jQobGqTUnYu3dv1Lzw+i7KLhUrVnTS06dPN7G9niiWhx56KKlzn3HGGU46vG6BEte5c2cnba8huummm5y8t956K2IZO3fudNKTJ0+O69x/+tOfnLS9tpDiY7eX/Qgc4NBHbcQj/Hgce11XeAsF+9b6yy+/POFzZRpHiIiIiMh77BARERGR97J6yqxGjRomDt9av3Xr1oTLW79+fdzHVqtWzcThob927dolfG6iXFWhQgUnfd9995k4vLP4Z599ZuJY06S28HR5kyZNTDxgwAAnz/6ZQck566yznLS97UF465JRo0alfL6uXbua+Omnn065PN8NGzbMxOFtYexd/8PbK9jmzZtn4gkTJjh5ixYtMvERRxzh5I0ZM8bELVq0iLPG2YMjREREROQ9doiIiIjIe+wQERERkfeyeg2RvRYh1jqe8G330TRu3NhJ33DDDVGPtedazz///LjKp+KxePFiE9vrRyg72Y+2sWMAWLlypYntR7KsWrXKOc7e6mLkyJFO3oUXXpiWelJkZcqUcdI9evQwcdWqVZ08ew3X/Pnzo5Zp//wOP4rHfizT4YcfnlhlyVnvAwA9e/Y0cfixUwUFBSa2b8+PJXyrfqtWrUx87733Onml/drkCBERERF5jx0iIiIi8l5WT5nZTjnlFCe9ZcuWDNWEikObNm1MbO90DBy6iziVXo0aNTKxPX1GpUN4CjScppJ36qmnOmn7tviwjz76yMT9+/d38tasWWNiexqzU6dOznHt27dPqp6lAUeIiIiIyHvsEBEREZH32CEiIiIi75WaNUSU23r16hUxJiKi9Dj33HNNPHXq1AzWJDtxhIiIiIi8xw4REREReY8dIiIiIvIeO0RERETkPXaIiIiIyHvsEBEREZH32CEiIiIi77FDRERERN5jh4iIiIi8J0qp+A8W2Qbg6+KrDhWhnlIqL12FsT0zLm3tybbMOF6buYXXZu6Iuy0T6hARERER5SJOmREREZH32CEiIiIi77FDRERERN5jh4iIiIi8xw4REREReY8dIiIiIvIeO0RERETkPXaIiIiIyHvsEBEREZH3/h9MJMvDalCXVwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<Figure size 720x864 with 10 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 定义比对可视化函数\n",
    "def plot_images_labels_prediction(images,  # 图像列表\n",
    "                                  labels,  # 标签列表\n",
    "                                  prediction,  # 预测值列表\n",
    "                                  index,  # 开始显示的索引\n",
    "                                  num=5):  # 缺省一次显示5张\n",
    "    fig = plt.gcf()  # 获取当前图表，get current figure\n",
    "    fig.set_size_inches(10, 12)  # 1英寸等于2.54cm\n",
    "\n",
    "    if num > 25:  # 最多显示25张图片\n",
    "        num = 25\n",
    "\n",
    "    for i in range(0, num):\n",
    "        ax = plt.subplot(5, 5, i + 1)  # 获取当前要处理的图片\n",
    "        ax.imshow(np.reshape(images[index], (28, 28)), cmap='binary')  # 显示第index个图像\n",
    "        title = 'label = ' + str(np.argmax(labels[index]))  # 显示标签的标题\n",
    "        if len(prediction) > 0:  # 如果有预测结果的话，添加显示预测的标题\n",
    "            title += ',predict = ' + str(prediction[index])\n",
    "        ax.set_title(title, fontsize=10)  # 显示图上的标题\n",
    "        # 不显示坐标轴\n",
    "        ax.set_xticks([])\n",
    "        ax.set_yticks([])\n",
    "        index += 1\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "# 可视化第500-509张测试图片的预测结果对比\n",
    "plot_images_labels_prediction(mnist.test.images,\n",
    "                              mnist.test.labels,\n",
    "                              prediction_result,\n",
    "                              500, 10)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
